package main

import "fmt"

// 如何设计一个排序系统

func main() {
	u1 := &user{id: 1, name: "user1"}
	u2 := &user{id: 2, name: "user2"}
	u3 := &user{id: 3, name: "user3"}
	u4 := &user{id: 4, name: "user4"}
	queue := &logQueue{queue: &userQueue{}}
	queue.push(u1)
	queue.push(u2)
	queue.push(u3)
	queue.push(u4)
	queue.pop()
	queue.remove(u3)
	queue.printQueue()
}

type user struct {
	id   int
	name string
	seq  int
}

type logQueue struct {
	queue *userQueue
}

func (p *logQueue) push(u *user) {
	p.queue.push(u)
	u.seq = p.queue.size()
}

func (p *logQueue) pop() {
	p.queue.pop()
	p.updateSeq()
}

func (p *logQueue) remove(u *user) {
	p.queue.remove(u)
	p.updateSeq()
}

func (p *logQueue) updateSeq() {
	for i, v := range p.queue.list() {
		v.seq = i + 1
	}
}

func (p *logQueue) printQueue() {
	for _, v := range p.queue.list() {
		fmt.Println(v)
	}
}

type userNode struct {
	data *user
	next *userNode
}

type userQueue struct {
	head *userNode
	end  *userNode
}

func (p *userQueue) push(u *user) {
	node := &userNode{
		data: u,
	}
	if p.head == nil {
		p.head = node
		p.end = node
	} else {
		p.end.next = node
		p.end = node
	}
}

func (p *userQueue) pop() {
	if p.head == nil {
		panic("队列已经空了")
	}
	p.head = p.head.next
	if p.head == nil {
		p.end = nil
	}
}

func (p *userQueue) remove(u *user) bool {
	if p.head == nil {
		return false
	}

	if p.head.data == u {
		p.head = p.head.next
		if p.head == nil {
			p.end = nil
		}
		return true
	}

	current := p.head
	for current.next != nil {
		if current.next.data == u {
			break
		}
	}

	if current.next == nil {
		return false
	}

	if current.next == p.end {
		p.end = current
	}
	current.next = current.next.next
	return true
}

func (p *userQueue) list() []*user {
	if p.head == nil {
		return nil
	}

	var users []*user

	current := p.head
	for current != nil {
		users = append(users, current.data)
		current = current.next
	}

	return users
}

func (p *userQueue) size() int {
	if p.head == nil {
		return 0
	}

	size := 0

	current := p.head
	for current != nil {
		size++
		current = current.next
	}

	return size
}
